"""
确保策略文件中没有恶意代码！！！
使用的库必须在系统requirements.txt之中
参与金额计算的数据使用Decimal计算！！！
注意回测性能：少用print打印，计算尽量在dataframe中一次完成
"""
from typing import *

import numpy as np
import pandas as pd
from decimal import Decimal

# 系统需要读取的配置
SYSTEM_CONF: Dict[str, Any] = {
    # 因子列表
    'factors': ['RVI'],
    # 指定币种数据，不指定则全选
    'symbols': ['ETHUSDT'],
    # 使用基础K线周期
    'Kline': 'hour',
    # 使用历史K线数量
    'historyKlineCount': 999,
    'param': 16
}


class SystemData:
    """
    代码不可更改！！！
    custom字段可以被赋值，务必保留标注的数据结构
    运行时系统会将特定数据注入
    账户信息只会在执行trade时被注入，选币时请勿使用
    批量交易接口是并行的，需要串行则在代码中多次调用
    """
    # ==== 数据信息 ====
    # 策略执行秒级时间戳（策略执行的理论时间，非实际时间）
    execute_timestamp: int = 0
    # 策略自定义存储内容，系统会将上次记录内容注入
    custom: Dict[str, Any] = {}
    # 因子的信号函数，输入输出都是dataframe，会将信号值添加到dataframe中
    factors: Mapping[str, Callable[..., pd.DataFrame]] = {}
    # ===== 回测相关 =====
    # 是否为回测
    is_backtest: bool = False
    # 回测记录数据
    backtest_data: Dict[str, pd.DataFrame] = {}


# +++++++ 以下为策略逻辑 ++++++++

def is_execute() -> bool:
    """
    判断是否需要执行策略逻辑
    :return:
    """
    # 整点执行
    return True


def pick(df: pd.DataFrame) -> pd.DataFrame:
    """
    选币计算
    选币计算不可使用账户数据，策略
    输入的dataframe:
    columns:
        symbol: str
        trade_type: int     0 现货 1 合约
        其余字段和币安完全相同
    :param df: 区间内所有K线数据
    :return: 选币结果
        columns:
    """
    df = SystemData.factors[SYSTEM_CONF['factors'][0]](df, *SYSTEM_CONF['param'])
    return df
